/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact z_huatai@qq.com
 *  
 */
package org.zfes.snowy.auth.biz.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zfes.snowy.auth.biz.dao.AuthRolePermissionMapper;
import org.zfes.snowy.auth.biz.model.AuthRole;
import org.zfes.snowy.auth.biz.model.AuthRolePermission;
import org.zfes.snowy.auth.biz.service.IAuthRolePermissionService;
import org.zfes.snowy.auth.biz.service.IAuthRoleService;
import org.zfes.snowy.auth.shiro.event.AuthCacheClearType;
import org.zfes.snowy.auth.shiro.event.AuthChangeEvent;
import org.zfes.snowy.base.dao.params.ParamMap;
import org.zfes.snowy.core.data.DataSet;
import org.zfes.snowy.core.idcenter.IDGenerator;
import org.zfes.snowy.core.util.ZAlert;
import org.zfes.snowy.core.util.ZAssert;
import org.zfes.snowy.core.util.ZObjectUtil;
import org.zfes.snowy.core.util.ZStrUtil;

@Service
@Lazy(true)
public class AuthRolePermissionServiceImpl  implements IAuthRolePermissionService{
	@Autowired
	private AuthRolePermissionMapper authRolePermissionMapper;
	@Autowired
	private IAuthRoleService authRoleService;
	@Autowired  
	private  ApplicationEventPublisher publisher;
//----------------------------------------------------------------------------------------------------	
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadPermIdsByRoleId(Long roleId, String appkey,Boolean enabled) {
		if(roleId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authRolePermissionMapper.selectPermIdsByRoleId(roleId,appkey,enabled);
	}
		
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<String> loadPermCodesByRoleCode(String roleCode, String appkey,Boolean enabled) {
		if(ZStrUtil.hasNoText(roleCode)||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authRolePermissionMapper.selectPermCodesByRoleCode(roleCode,appkey, enabled);
	}

	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadPermIdsByRoleCode(String roleCode,String appkey, Boolean enabled) {
		if(ZStrUtil.hasNoText(roleCode)||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authRolePermissionMapper.selectPermIdsByRoleCode(roleCode,appkey, enabled);
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<String> loadPermCodesByRoleId(Long roleId, String appkey, Boolean enabled) {
		if(roleId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authRolePermissionMapper.selectPermCodesByRoleId(roleId,appkey,enabled);
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=false)	
	@Override
	public void addPermsToRolePerm(List<Long> permissionsIds, Long roleId) {
		if(roleId==null||ZObjectUtil.isEmpty(permissionsIds)){
			ZAlert.Error("请选择数据");
		}
		Optional<AuthRole> authRoleOP=authRoleService.loadAuthRole(roleId);
		ZAssert.notEmpty(authRoleOP, "未查到角色数据");
		ZAssert.isTrue(authRoleOP.get().getEnabled(), "角色状态错误");
		
		permissionsIds=permissionsIds.stream().distinct().collect(Collectors.toList());
		
		removePermsFromRolePerm(permissionsIds,roleId);
		
		List<AuthRolePermission> rolePermissionList= permissionsIds.stream().map(permId-> new AuthRolePermission(IDGenerator.genLongId(),permId,roleId)).collect(Collectors.toList());	
	    authRolePermissionMapper.batchInsertRolePermission(rolePermissionList);
	    this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoByRole,authRoleOP.get().getRoleCode()));  
		
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=false)	
	@Override
	public void removePermsFromRolePerm(List<Long> permIds, Long roleId) {
		if(roleId==null||ZObjectUtil.isEmpty(permIds)){
			ZAlert.Error("请选择数据");
		}
		
		Optional<AuthRole> authRoleOP=authRoleService.loadAuthRole(roleId);
		ZAssert.notEmpty(authRoleOP, "未查到角色数据");
		ZAssert.isTrue(authRoleOP.get().getEnabled(), "角色状态错误");
		
		authRolePermissionMapper.deleteFromRolePermission(permIds, roleId);
		
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoByRole,authRoleOP.get().getRoleCode()));
		
	}
//,String appKey, Long moduleId, String permCode,String permName, Long roleId,Boolean isInRole
	@Transactional(rollbackFor=Exception.class,readOnly=true)	
	@Override
	public DataSet loadPermDataSetForRoleAssign(Boolean isInRole ,Map<String, Object> params ) {
		ParamMap pm=ParamMap.filterParam(params);
		Optional<String> appKey=pm.getStr("appKey");
		Optional<Long> roleId=pm.getLong("roleId");
		if(!roleId.isPresent()||isInRole==null||!appKey.isPresent()){
			return DataSet.emptyDS();
		}
		
		pm.getStr("name").ifPresent(v->pm.updateParam( "name", "%"+v+"%"));
		pm.getStr("permCode").ifPresent(v->pm.updateParam( "permCode", "%"+v+"%"));
		
		if(isInRole){
			return DataSet.newDS(authRolePermissionMapper.selectPermsInRoleCount(pm), authRolePermissionMapper.selectPermsInRole(pm));
		} else{
			return DataSet.newDS(authRolePermissionMapper.selectPermsNotInRoleCount(pm), authRolePermissionMapper.selectPermsNotInRole(pm));
		}
	}
	
}
